3.5. Rules of Injection 注入规则
前面的章节中已经给出注释类型的例子,主要用标注方法参数,也可以通过对类的域进行注解将值注入到这些类型。
本节介绍了在注释类型上注入值的规则。注入可以用在属性,构造函数参数,资源/子资源/子资源定位方法的参数和 bean setter方法。以下介绍的这些注入的情况下:
Example 3.23. 注入
@Path("{id:\\d+}")
public class InjectedResource {
// 注入到属性
@DefaultValue("q") @QueryParam("p")
private String p;
// 注入到构造函数参数
public InjectedResource(@PathParam("id") int id) { ... }
// 注入到资源参数
@GET
public String get(@Context UriInfo ui) { ... }
// 注入子资源方法参数
@Path("sub-id")
@GET
public String get(@PathParam("sub-id") String id) { ... }
// 注入子资源方法参数定位器方法参数
@Path("sub-id")
public SubResource getSubResource(@PathParam("sub-id") String id) { ... }
// 注入 bean setter 方法
@HeaderParam("X-header")
public void setHeader(String header) { ... }
}
有一些限制,当注射到一个生命周期为单域的资源类。在这种情况下,类的属性或构造函数的参数不能被注入请求特定的参数。所以,例如,以下是不允许的。
Example 3.24. 错误!注入单域
@Path("resource")
@Singleton
public static class MySingletonResource {
@QueryParam("query")
String param; //错误:不能将特定参数注入单例资源,
//会使程序初始化失败
@GET
public String get() {
return "query param: " + param;
}
}
上面的例子验证了应用程序不能为单资源注入请求特定的参数,否则验证失败的。同样的例子,如果查询的参数将被注入到一个单例构造函数参数则失败。换句话说,如果你希望一个资源实例的服务很多请求,则资源实例不能绑定到一个特定的请求参数。
存在例外,特定请求对象可以注入到构造函数或类属性。这些对象的运行时注入的代理可以同时服务多个请求。这些请求的对象是HttpHeaders, Request, UriInfo, SecurityContex。这些代理可以使用 @Context 注释进行注入。下面的示例展示将代理注入单资源类。
Example 3.25. Injection of proxies into singleton
@Path("resource")
@Singleton
public static class MySingletonResource {
@Context
Request request; // 这个是允许的:
//请求的代理将会被注入进单例
public MySingletonResource(@Context SecurityContext securityContext) {
// 这个也是允许的:
// SecurityContext的代理将会被注入进单例
}
@GET
public String get() {
return "query param: " + param;
}
}
总结,可以为以下结构注入:
Java 构造 | 描述 |
---|---|
Class fields | 将值直接注入类属性。这属性 可以是 private 但一定不能是 final 。除了上面提到的代理类型方法外,不能用在单例范围。 |
Constructor parameters | 构造函数会调用注入值。如果多个构造函数其中存在一个最可注的射参数则将被调用。除了上面提到的代理类型方法外,不能用在单例范围。 |
Resource methods | 资源的方法(带有 @GET, @POST, …注解)包含的参数可以在执行时注射。可以在任何范围使用。 |
Sub resource locators | 子资源的方法(带有 @GET, @POST, …注解)包含的参数可以在执行时注射。可以在任何范围使用。 |
Setter methods | 值可以被注入 setter 方法将初始化属性,而不是直接将值注入属性的。注射只能用于 @Context 注释。这意味着它不能使用,例如将查询参数注入,但可以用在请求注入。setter 方法将会在对象创建后执行,且只有一次。该方法的名称不必要有一个 setter 模式。除了上面提到的代理类型,不能在单例范围内使用。 |
下面的示例显示所有可能的值可以被注入的 Java 构建函数。
Example 3.26. 可能注入的例子
@Path("resource")
public static class SummaryOfInjectionsResource {
@QueryParam("query")
String param; // injection into a class field 注入类的属性
@GET
public String get(@QueryParam("query") String methodQueryParam) {
// injection into a resource method parameter 注入资源的方法参数
return "query param: " + param;
}
@Path("sub-resource-locator")
public Class<SubResource> subResourceLocator(@QueryParam("query") String subResourceQueryParam) {
// injection into a sub resource locator parameter注入子资源定位器参数
return SubResource.class;
}
public SummaryOfInjectionsResource(@QueryParam("query") String constructorQueryParam) {
// injection into a constructor parameter注入构造器的参数
}
@Context
public void setRequest(Request request) {
// injection into a setter method注入setter方法
System.out.println(request != null);
}
}
public static class SubResource {
@GET
public String get() {
return "sub resource";
}
}
@FormParam 注释是特别的,仅可利用资源和子资源的方法。这是因为它从请求实体中提取信息